#!/usr/bin/env bun
/**
 * Prebuild script that scans the .agents/ directory and generates a TypeScript
 * module with all agent definitions embedded as static data.
 *
 * This allows agent definitions to be bundled into the CLI binary without
 * requiring runtime filesystem access to the .agents/ directory.
 *
 * Run this before building the binary:
 *   bun run scripts/prebuild-agents.ts
 */

import * as fs from 'fs'
import * as path from 'path'

const AGENTS_DIR = path.join(import.meta.dir, '../../.agents')
const OUTPUT_FILE = path.join(import.meta.dir, '../src/agents/bundled-agents.generated.ts')

interface AgentDefinition {
  id: string
  displayName?: string
  [key: string]: any
}

/**
 * Recursively get all TypeScript files from a directory
 */
function getAllTsFiles(dir: string): string[] {
  const files: string[] = []

  try {
    const entries = fs.readdirSync(dir, { withFileTypes: true })

    for (const entry of entries) {
      const fullPath = path.join(dir, entry.name)

      if (entry.isDirectory()) {
        // Skip __tests__ and node_modules directories
        if (entry.name === '__tests__' || entry.name === 'node_modules' || entry.name === 'types') {
          continue
        }
        files.push(...getAllTsFiles(fullPath))
      } else if (
        entry.isFile() &&
        entry.name.endsWith('.ts') &&
        !entry.name.endsWith('.d.ts') &&
        !entry.name.endsWith('.test.ts')
      ) {
        files.push(fullPath)
      }
    }
  } catch (error) {
    console.error(`Error reading directory ${dir}:`, error)
  }

  return files
}

/**
 * Load and process an agent definition from a TypeScript file
 */
async function loadAgentDefinition(filePath: string): Promise<AgentDefinition | null> {
  try {
    // Use dynamic import to load the module
    const module = await import(filePath)
    const definition = module.default

    if (!definition || !definition.id || !definition.model) {
      return null
    }

    // Process the definition - convert handleSteps function to string
    const processed: AgentDefinition = { ...definition }
    
    if (typeof processed.handleSteps === 'function') {
      processed.handleSteps = processed.handleSteps.toString()
    }

    return processed
  } catch (error) {
    console.error(`Error loading agent from ${filePath}:`, error)
    return null
  }
}

/**
 * Generate the bundled agents TypeScript file
 */
function generateBundledAgentsFile(agents: Record<string, AgentDefinition>): string {
  const agentCount = Object.keys(agents).length
  
  return `/**
 * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
 * 
 * This file is generated by scripts/prebuild-agents.ts
 * It contains all bundled agent definitions from the .agents/ directory.
 * 
 * Generated at: ${new Date().toISOString()}
 * Agent count: ${agentCount}
 */

import type { LocalAgentInfo } from '../utils/local-agent-registry'

/**
 * All bundled agent definitions keyed by their ID.
 * These are the default Codebuff agents that ship with the CLI binary.
 */
export const bundledAgents: Record<string, any> = ${JSON.stringify(agents, null, 2)};

/**
 * Get bundled agents as LocalAgentInfo format for the CLI
 */
export function getBundledAgentsAsLocalInfo(): LocalAgentInfo[] {
  return Object.values(bundledAgents).map((agent) => ({
    id: agent.id,
    displayName: agent.displayName || agent.id,
    filePath: '[bundled]',
    isBundled: true,
  }));
}

/**
 * Get all bundled agent IDs
 */
export function getBundledAgentIds(): string[] {
  return Object.keys(bundledAgents);
}

/**
 * Check if an agent ID is a bundled agent
 */
export function isBundledAgent(agentId: string): boolean {
  return agentId in bundledAgents;
}
`
}

async function main() {
  const DEBUG = false
  if (DEBUG) {
    console.log('🔍 DEBUG: Scanning .agents/ directory...')
  }
  
  if (!fs.existsSync(AGENTS_DIR)) {
    console.error(`Error: .agents/ directory not found at ${AGENTS_DIR}`)
    // process.exit(1)
    return
  }

  const tsFiles = getAllTsFiles(AGENTS_DIR)
  if (DEBUG) {
    console.log(`📁 DEBUG: Found ${tsFiles.length} TypeScript files`)
  }

  const agents: Record<string, AgentDefinition> = {}
  let loadedCount = 0
  let skippedCount = 0

  for (const filePath of tsFiles) {
    const relativePath = path.relative(AGENTS_DIR, filePath)
    const definition = await loadAgentDefinition(filePath)
    
    if (definition) {
      agents[definition.id] = definition
      loadedCount++
      if (DEBUG) {
        console.log(`  ✅ DEBUG: ${definition.id} (${relativePath})`)
      }
    } else {
      skippedCount++
      if (DEBUG) {
        console.log(`  ⏭️ DEBUG: Skipped: ${relativePath} (no valid default export)`)
      }
    }
  }

  if (DEBUG) {
    console.log(`\n📦 DEBUG: Loaded ${loadedCount} agents, skipped ${skippedCount} files`)
  }

  // Generate the output file
  const output = generateBundledAgentsFile(agents)
  
  // Ensure output directory exists
  const outputDir = path.dirname(OUTPUT_FILE)
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true })
  }

  fs.writeFileSync(OUTPUT_FILE, output, 'utf-8')
  if (DEBUG) {
    console.log(`\n✨ DEBUG: Generated ${OUTPUT_FILE}`)
    console.log(`   DEBUG: ${Object.keys(agents).length} agents bundled`)
  }
}

main().catch((error) => {
  console.error('Fatal error:', error)
  process.exit(1)
})
